﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using Infrastructure.Cache;
using SqlSugar;

namespace Infrastructure.DBSqlSugar
{
    public class DBSqlSugar
    {
        /// <summary>
        /// 数据库操作实例
        /// </summary>
        private readonly ISqlSugarClient db;

        public DBSqlSugar(ISqlSugarClient sugarClient)
        {
            db = sugarClient;
        }

        /// <summary>
        /// 表内数据总量
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="db"></param>
        /// <returns></returns>
        public int GetCount<T>(Expressionable<T> exp) where T : class, new()
        {
            //获取总量
            return db.CopyNew().Queryable<T>().Where(exp.ToExpression()).Count();
        }

        /// <summary>
        /// （分表时）表内数据总量
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="db"></param>
        /// <returns></returns>
        public int GetCount<T>(Expressionable<T> exp, DateTime StartTime, DateTime EndTime) where T : class, new()
        {
            //获取总量
            return db.CopyNew().Queryable<T>().Where(exp.ToExpression()).SplitTable(StartTime, EndTime).Count();
        }

        /// <summary>
        /// 查询T表全部数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="db"></param>
        /// <returns></returns>
        public List<T> GetListModel<T>()
        {
            List<T> Data = db.CopyNew().Queryable<T>().ToList();
            return Data;
        }

        /// <summary>
        /// 按条件查询T表全部数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="db"></param>
        /// <returns></returns>
        public List<T> GetListModel<T>(Expressionable<T> exp) where T : class, new()
        {
            var TabData = db.CopyNew().Queryable<T>().Where(exp.ToExpression()).ToList();
            return TabData;
        }

        /// <summary>
        /// 查询T表全部数据（分页排序）（分表模式：模糊表名称定位一张表）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="page">页号</param>
        /// <param name="limit">页量</param>
        /// <param name="exp">查询条件</param>
        /// <param name="TabName">指定表名称</param>
        /// <param name="FiledName">排序字段</param>
        /// <param name="OrderByType">排序方式</param>
        /// <param name="db">数据库连接串</param>
        /// <returns></returns>
        public List<T> GetListModel<T>(int page, int limit, Expressionable<T> exp, string FiledName, string OrderByType, string TabName = "") where T : class, new()
        {
            //通过类中属性名获取数据库字段名(防注入)
            var orderByFieldName = db.EntityMaintenance.GetDbColumnName<T>(FiledName);

            //分表模式时
            if (!string.IsNullOrEmpty(TabName))
            {
                //配置分表模式
                db.CurrentConnectionConfig.ConfigureExternalServices.SplitTableService = new SplitService();

                List<string> asssss = new List<string>();

                //返回数据库中的数据
                return db.CopyNew().Queryable<T>().Where(exp.ToExpression()).SplitTable(tas => tas.InTableNames(GetSplitTableName<T>(TabName))).OrderBy(orderByFieldName + " " + OrderByType).ToPageList(page, limit);
            }
            //不分表时
            else
            {
                return db.CopyNew().Queryable<T>().Where(exp.ToExpression()).OrderBy(orderByFieldName + " " + OrderByType).ToPageList(page, limit);
            }
        }

        /// <summary>
        /// 根据查询条件查询数据（支持分表）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="ID">主键</param>
        /// <param name="db"></param>
        /// <returns></returns>
        public T GetModel<T>(string ID, bool IsSplitTable = false) where T : class, new()
        {
            //配置了分表
            if (IsSplitTable)
            {
                //配置分表模式
                db.CurrentConnectionConfig.ConfigureExternalServices.SplitTableService = new SplitService();
                return db.CopyNew().Queryable<T>().SplitTable(tabs => tabs).Where("ID=@ID", new { ID }).First();
            }
            else
            {

                return db.CopyNew().Queryable<T>().Where("ID=@ID", new { ID }).First();
            }
        }
    
        /// <summary>
        /// 根据查询条件查询数据（支持分表），返回最后一条记录
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="exp">查询条件</param>
        /// <param name="IsSplitTable">是否分表</param>
        /// <returns></returns>
        public T GetModel<T>(Expressionable<T> exp, bool IsSplitTable = false) where T : class, new()
        {
            if (IsSplitTable)
            {
                db.CurrentConnectionConfig.ConfigureExternalServices.SplitTableService = new SplitService();
                return db.CopyNew()
                         .Queryable<T>()
                         .SplitTable(tabs => tabs)
                         .Where(exp.ToExpression())
                         .OrderBy("ID desc")   // 按主键ID倒序，取最后一条
                         .First();
            }
            else
            {
                return db.CopyNew()
                         .Queryable<T>()
                         .Where(exp.ToExpression())
                         .OrderBy("ID desc")   // 按主键ID倒序，取最后一条
                         .First();
            }
        }

        /// <summary>
        /// 根据查询条件查询数据（支持分表）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="ID">主键</param>
        /// <param name="db"></param>
        /// <returns></returns>
        public T GetModelCache<T>(string ID, bool IsSplitTable = false) where T : class, new()
        {
            if (string.IsNullOrEmpty(ID))
            {

                return null;
            }
            string cacheKey = typeof(T).ToString() + "_" + ID.ToString();


            //等待返回的数据
            T model = null;

            //配置了分表
            if (IsSplitTable)
            {
                //配置分表模式
                db.CurrentConnectionConfig.ConfigureExternalServices.SplitTableService = new SplitService();
                model = db.CopyNew().Queryable<T>().SplitTable(tabs => tabs).Where("ID=@ID", new { ID }).First();
            }
            else
            {
                model = db.CopyNew().Queryable<T>().Where("ID=@ID", new { ID }).First();
            }

            return model;
        }

        /// <summary>
        /// 数据库表的所有分表
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="db"></param>
        /// <returns></returns>
        public List<SplitTableInfo> GetTables<T>() where T : class, new()
        {
            //用例1：获取所有表表名 ，可以用于循环处理每个表
            return db.SplitHelper<T>().GetTables();
        }

        /// <summary>
        /// 添加数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <returns></returns>
        public int AddModel<T>(T t, bool IsSplitTable = false) where T : class, new()
        {
            //检查是否需要分表
            if (IsSplitTable)
            {
                //配置分表模式
                db.CurrentConnectionConfig.ConfigureExternalServices.SplitTableService = new SplitService();
                //分表模式
                return db.CopyNew().Insertable(t).SplitTable().ExecuteCommand();
            }
            else
            {
                //不分表模式
                return db.CopyNew().Insertable(t).ExecuteCommand();
            }
        }

        /// <summary>
        /// 更新数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <returns>受影响行数</returns>
        public int UPModel<T>(T t, bool IsSplitTable = false) where T : class, new()
        {
            if (IsSplitTable)
            {
                //受影响行数
                return db.CopyNew().Updateable(t).SplitTable().ExecuteCommand();
            }
            else
            {
                //受影响行数
                return db.CopyNew().Updateable(t).ExecuteCommand();
            }
        }

        /// <summary>
        /// 分表时根据值获取分表的全称
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="db"></param>
        /// <returns></returns>
        public string GetSplitTableName<T>(string Val) where T : class, new()
        {
            //配置分表模式
            db.CurrentConnectionConfig.ConfigureExternalServices.SplitTableService = new SplitService();

            return db.SplitHelper<T>().GetTableName(Val);//有重载
        }

        /// <summary>
        /// 根据条件删除数据（支持分表）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="exp">删除条件</param>
        /// <param name="IsSplitTable">是否分表</param>
        /// <returns>受影响行数</returns>
        public int DELModel<T>(Expression<Func<T, bool>> exp, bool IsSplitTable = false) where T : class, new()
        {
            if (IsSplitTable)
            {
                return db.CopyNew().Deleteable<T>().Where(exp).SplitTable().ExecuteCommand();
            }
            else
            {
                return db.CopyNew().Deleteable<T>().Where(exp).ExecuteCommand();
            }
        }

        /// <summary>
        /// 根据主键ID删除（不支持分表）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="ID">主键ID</param>
        /// <param name="IsSplitTable">是否分表</param>
        /// <returns>受影响行数</returns>
        public int DELModel<T>(string ID) where T : class, new()
        {
            return db.CopyNew()
                          .Deleteable<T>()
                          .Where("ID=@ID", new { ID })
                          .ExecuteCommand();
        }

    }
}
